#!/usr/bin/python3
# -*- coding: UTF-8 -*-
import json
import os
import platform
import subprocess
import sys
import tempfile
import time

if sys.version_info.major == 3:
    import urllib.request as urlRequest
else:
    import urllib2 as urlRequest

rootUrl = "http://upgrade.guanjieai.com"
apiCheckUpgrade = "/node/check_upgrade"
apiUpgradeReport = "/node/upgrade_report"
logMsg = []
workDir = os.path.dirname(os.path.abspath(__file__))
env = 'test' if len(sys.argv) < 2 else sys.argv[1]
debug = False if len(sys.argv) < 3 else sys.argv[2] == 'debug'


def getDeviceId():
    deviceId = ""
    try:
        with open('/usr/local/bin/p2puid', 'r') as f:
            p2pData = str(f.read())
            deviceId = p2pData.strip(" ")
            deviceId = deviceId.strip("\n")
    except:
        return ""
    return deviceId


# 查询是否需要更新
def checkUpgrade(checkUpgradeData):
    try:
        url = rootUrl + apiCheckUpgrade
        data = str(json.dumps(checkUpgradeData)).encode('utf-8')
        header = {'Content-Type': 'application/json'}
        req = urlRequest.Request(url=url, data=data, headers=header)
        response = urlRequest.urlopen(req).read()
        jsonData = json.loads(response.decode('utf-8'))
        log(url + " => " + str(response.decode('utf-8')))
        if jsonData.get('code') != 0:
            return None
        if jsonData.get('data', None) is None:
            return None
    except Exception as e:
        log('apiCheckUpgrade error: '+str(e))
        return None
    else:
        return jsonData.get('data', None)


# 上报更新结果信息
def upgradeReport(success, message, versionData):
    try:
        url = rootUrl + apiUpgradeReport
        params = {
            "upgrade": True if success else False,
            "message": message,
            "version_data": versionData
        }
        data = str(json.dumps(params))
        data = data.encode('utf-8')
        log("report data: " + str(data))
        header = {'Content-Type': 'application/json'}
        req = urlRequest.Request(url=url, data=data, headers=header)
        response = urlRequest.urlopen(req).read()
        log(str(response))
    except IOError:
        log("IO ERR")
    else:
        log("ok")


'''
获取本地版本信息
包含设备，版本，环境信息
'''


def getLocalVersion(deviceId):
    try:
        sub = subprocess.Popen(workDir + "/enode version --config=/opt/enode/config.yaml", shell=True, stdout=subprocess.PIPE)
        sub.wait()
        verData = sub.stdout.read()
        verData = str(verData, encoding='utf-8')
        verJson = json.loads(verData)
        #判断架构
        arch = platform.machine()
        if arch == "x86_64":
            arch = "amd64"
        elif arch == "aarch64":
            arch = "arm64"

        return dict({
            'device_id': deviceId,
            'node_id': verJson["node_id"],
            'version': verJson["version"],  # 版本号
            'commit_id':  verJson["commit_hash"],
            'os': platform.system().lower(),
            'arch': arch,
            'env': env  # 环境
        })
    except Exception as e:
        log("[{uid}]getLocalVersion error: {err}".format(uid=deviceId, err=str(e)))
        return None


# 检查并更新
def checkAndUpdate(deviceId):
    try:
        log("checkAndUpdate")
        checkUpgradeData = getLocalVersion(deviceId)
        if checkUpgradeData is None:
            raise Exception("version info get error")
        jsonData = checkUpgrade(checkUpgradeData)
        if jsonData is None:
            log("checkUpgradeData  error  ")
            return
        if not jsonData.get('upgrade', False):
            log("don't upgrade")
            return
        if jsonData.get('download_url', "") == "":
            log("node download url error")
            return
        log("upgrade " + checkUpgradeData['version'] + " to " + jsonData['version'] + ', pkg => ' + jsonData['download_url'])
        newVersion = localUpgrade(jsonData['download_url'], deviceId)
        print(newVersion)
        if newVersion is None:
            raise Exception("upgrade failed")
        upgradeReport(True, 'upgrade success', newVersion)
    except Exception as e:
        log("checkAndUpgrade error: " + str(e))
        upgradeReport(False, logMsg, getLocalVersion(deviceId))


def localUpgrade(downloadUrl, deviceId):
    try:
        res=os.system("cd {tmpDir} && rm -rf ./node_install.sh && wget {rootUrl}/node_install.sh && chmod +x node_install.sh && sudo {tmpDir}/node_install.sh update {downloadUrl} --env={env}".format(tmpDir=tempfile.gettempdir(),rootUrl=rootUrl, downloadUrl=downloadUrl, env=env))
        log("upgrade enode ok")
        if res != 0:
            raise Exception("upgrade fail!")
        return getLocalVersion(deviceId)
    except Exception as e:
        log("upgrade error: ".format(str(e)))
        return None

def log(errMsg):
    msg = '[{time}] {msg}'.format(time=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), msg=errMsg)
    logMsg.append(msg)
    print(msg)


if __name__ == '__main__':
    checkAndUpdate(getDeviceId())